package com.pubinfo.passbook.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import com.mashape.unirest.request.body.RequestBodyEntity;
import com.pubinfo.passbook.api.config.FileForwardConfig;
import com.pubinfo.passbook.api.eip.UserInfoService;
import com.pubinfo.passbook.api.service.ForwardFileService;
import com.pubinfo.passbook.common.model.dto.MDM.TSourceArtificialParam;
import com.pubinfo.passbook.common.model.dto.file.ArtificialFileParam;
import com.pubinfo.passbook.common.model.dto.file.ArtificialParam;
import com.pubinfo.passbook.common.model.dto.file.UploadFileParam;
import com.pubinfo.passbook.common.service.dubbo.DubboService;
import lombok.SneakyThrows;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

@Service
public class ForwardFileServiceImpl implements ForwardFileService {
    
    @Value("${post.url}")
    String postUrl;
    @Value("${post.http-port}")
    String httpPort;
    @Resource
    FileForwardConfig config;
    @Autowired
    UserInfoService userInfoService;
    
    @Autowired
    DubboService dubboService;
    
    @Override
    public String saveArtificial(ArtificialParam artificialParam) {
        //检查是否为外包人员，如果是外包人员，则不能报销
        // dubboService.getPersonsDetailByIdNo();
        if (artificialParam.getTSourceArtificial().getAcct().startsWith("W")) {
            throw new IllegalArgumentException("外包人员不能报销");
        }
        return postArtificialFile(artificialParam, postUrl + ":" + httpPort + config.getSaveArtificialUrl());
    }
    
    @Override
    public String uploadInvoiceById(UploadFileParam uploadFileParam) throws UnirestException {
        return postInvoiceFile(uploadFileParam, postUrl + ":" + httpPort + config.getUploadInvoiceByIdUrl());
    }

    @Override
    public String uploadArtificialFile(ArtificialFileParam artificialFileParam) throws UnirestException {
        return postuploadArtificialFile(artificialFileParam, postUrl + ":" + httpPort + config.getUploadArtificialFile());
    }

    @Override
    public String selectArtificialByCreateUser(TSourceArtificialParam param) throws UnirestException {
        param.setUser(userInfoService.getCurrentAcct());
        return postSelectArtificialByCreateUser(param, postUrl + ":" + httpPort + config.getSelectArtificialByCreateUser());
    }

    @Override
    public String deleteFile(List<String> id) throws UnirestException {
        return postDeleteFile(id, postUrl + ":" + httpPort + config.getDeleteFile());
    }

    @Override
    public String saveTFileEnclosure(MultipartFile file) throws UnirestException {
        return postTFileEnclosure(file, postUrl + ":" + httpPort + config.getSaveTFileEnclosure());
    }

    @Override
    public void acctDownload(HttpServletRequest request, HttpServletResponse response, String id) throws UnirestException {
        GetRequest getRequest = postAccDownload(postUrl + ":" + httpPort + config.getAcctDownload() + id);
        String s = getRequest.asString().getHeaders().toString();
        Pattern r = compile("filename=\".+\"");
        Matcher m = r.matcher(s);
        if (m.find()) {
            String fileName = m.group(0);
            fileName = fileName.replace("filename=", "").replace("\"", "");
            response.setCharacterEncoding(request.getCharacterEncoding());
            response.setContentType("application/octet-stream");
            InputStream fis = null;
            try {
                fis = getRequest.asBinary().getBody();
                response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                IOUtils.copy(fis, response.getOutputStream());
                response.flushBuffer();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public void acctDownloadZip(HttpServletRequest request, HttpServletResponse response, List<String> id) throws IOException, UnirestException {
        RequestBodyEntity getRequest = postAcctDownloadZip(postUrl + ":" + httpPort + config.getAcctDownloadZip(),JSONObject.toJSONString(id));
        String s = getRequest.asString().getHeaders().toString();
        Pattern r = compile("filename=\".+\"");
        Matcher m = r.matcher(s);
        if (m.find()) {
            String fileName = m.group(0);
            fileName = fileName.replace("filename=", "").replace("\"", "");
            response.setCharacterEncoding(request.getCharacterEncoding());
            response.setContentType("application/octet-stream");
            InputStream fis = null;
            try {
                fis = getRequest.asBinary().getBody();
                response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                IOUtils.copy(fis, response.getOutputStream());
                response.flushBuffer();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private GetRequest postAccDownload(String url) {
        //Unirest.setTimeouts(0, 0);
        GetRequest response = Unirest.get(url)
            .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)");
        return response;
    }

    private RequestBodyEntity postAcctDownloadZip(String url, String json) throws UnirestException {
        //Unirest.setTimeouts(0, 0);
        Unirest.setTimeouts(0, 0);
        RequestBodyEntity response = Unirest.post(url)
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                .header("Content-Type", "application/json")
                .body(json);
        return response;
    }
    
    @SneakyThrows
    private String postArtificialFile(ArtificialParam artificialParam, String url) {
        //Unirest.setTimeouts(0, 0);
        
        String nsrsbh = dubboService.getUserNsrsbhByAcct(artificialParam.getTSourceArtificial().getAcct());
        HttpResponse<String> response = Unirest.post(url)
            .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
            .field("invoiceFile", getFiles(artificialParam.getInvoiceFile()))
            .field("passbookFile", getFiles(artificialParam.getPassbookFile()))
            .field("enclosureFile", getFiles(artificialParam.getEnclosureFile()))
            .field("tSourceArtificial.payAmount", artificialParam.getTSourceArtificial().getPayAmount())
            .field("tSourceArtificial.approvedAmount", artificialParam.getTSourceArtificial().getApprovedAmount())
            .field("tSourceArtificial.number", artificialParam.getTSourceArtificial().getNumber())
            .field("tSourceArtificial.isReimbursement", artificialParam.getTSourceArtificial().getIsReimbursement())
            .field("tSourceArtificial.acct", artificialParam.getTSourceArtificial().getAcct())
            .field("tSourceArtificial.createUser", userInfoService.getCurrentAcct())
            .field("tSourceArtificial.nsrsbh", nsrsbh)
            .field("tSourceArtificial.type", artificialParam.getTSourceArtificial().getType()).field("invoiceIds", artificialParam.getInvoiceIds())
                .asString();
        return response.getBody();
    }

    private String postSelectArtificialByCreateUser(TSourceArtificialParam param, String url) throws UnirestException {
        //Unirest.setTimeouts(0, 0);
        String s = JSONObject.toJSON(param).toString();
        HttpResponse<String> response = Unirest.post(url)
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                .header("Content-Type", "application/json")
                .body(JSONObject.toJSON(param).toString())
                .asString();
        return response.getBody();
    }

    private String postDeleteFile(List<String> id, String url) throws UnirestException {
        //Unirest.setTimeouts(0, 0);
        String s = JSONObject.toJSON(id).toString();
        HttpResponse<String> response = Unirest.post(url)
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                .header("Content-Type", "application/json")
                .body(JSONObject.toJSON(id).toString())
                .asString();
        return response.getBody();
    }

    private String postInvoiceFile(UploadFileParam uploadFileParam, String url) throws UnirestException {
        //Unirest.setTimeouts(0, 0);
        HttpResponse<String> response = Unirest.post(url)
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                .field("file", getFiles(uploadFileParam.getFile()))
                .field("acct", uploadFileParam.getAcct())
                .field("id", uploadFileParam.getId())
                .field("type", uploadFileParam.getType())
                .asString();
        return response.getBody();
    }

    private String postTFileEnclosure(MultipartFile file, String url) throws UnirestException {
        //Unirest.setTimeouts(0, 0);
        HttpResponse<String> response = Unirest.post(url)
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                .field("file", transferToFile(file))
                .asString();
        return response.getBody();
    }

    private String postuploadArtificialFile(ArtificialFileParam artificialFileParam, String url) throws UnirestException {
        //Unirest.setTimeouts(0, 0);
        HttpResponse<String> response = Unirest.post(url)
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                .field("invoiceFile", transferToFile(artificialFileParam.getInvoiceFile()))
                .field("artificialId", artificialFileParam.getArtificialId())
                .field("type", artificialFileParam.getType())
                .asString();
        return response.getBody();
    }

    private List<File> getFiles(List<MultipartFile> multipartFiles) {
        List<File> files = new ArrayList<>();
        for (MultipartFile multipartFile : multipartFiles) {
            files.add(transferToFile(multipartFile));
        }
        return files;
    }

    private List<File> transferToFile(List<MultipartFile> multipartFiles) {
        List<File> list=new ArrayList<>();
//        选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
        for (MultipartFile multipartFile : multipartFiles) {
            File file = null;
            try {
                String originalFilename = multipartFile.getOriginalFilename();
                int index= originalFilename.lastIndexOf(".");
                file = File.createTempFile(originalFilename.substring(0,index),originalFilename.substring(index));
                multipartFile.transferTo(file);
                list.add(file);
                file.deleteOnExit();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    private File transferToFile(MultipartFile multipartFile) {
//        选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            int index= originalFilename.lastIndexOf(".");
            file = File.createTempFile(originalFilename.substring(0,index),originalFilename.substring(index));
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }
}
